﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls.Primitives;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Documents;
using System.Windows.Media;

namespace Relay.UI.Controls.Docking.Primitives {
    /// <summary>
    /// Provides a control to resize docked elements in a DockManager
    /// </summary>
    public class SplitPanelSplitter : Thumb {
        #region Fields
        private SplitPanel _host = null;
        private FrameworkElement _elementBefore = null;
        private FrameworkElement _elementAfter = null;
        private SplitterAdorner _adorner = null;
        private Orientation _orientation = Orientation.Horizontal;
        private double _minElementDelta = 0.0;
        private double _maxElementDelta = 0.0;
        #endregion

        #region Constructor
        static SplitPanelSplitter() {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SplitPanelSplitter),
                new FrameworkPropertyMetadata(typeof(SplitPanelSplitter)));

            EventManager.RegisterClassHandler(typeof(SplitPanelSplitter), Thumb.DragStartedEvent,
                new DragStartedEventHandler(DragStartedHandler));
            EventManager.RegisterClassHandler(typeof(SplitPanelSplitter), Thumb.DragDeltaEvent,
                            new DragDeltaEventHandler(DragDeltaHandler));
            EventManager.RegisterClassHandler(typeof(SplitPanelSplitter), Thumb.DragCompletedEvent,
                new DragCompletedEventHandler(DragCompletedHandler));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DockManagerSplitter"/> class.
        /// </summary>
        /// <param name="element">The element.</param>
        public SplitPanelSplitter(FrameworkElement elementBefore, FrameworkElement elementAfter,
                                  SplitPanel host) {
            _elementBefore = elementBefore;
            _elementAfter = elementAfter;
            _host = host;

            _orientation = host.Orientation;
            _adorner = new SplitterAdorner(this);

            Cursor = (_orientation == Orientation.Horizontal) ? Cursors.SizeWE : Cursors.SizeNS;
        }
        #endregion

        #region Private Methods
        private void ThumbDragStarted(DragStartedEventArgs e) {
            double beforeSize = SplitPanel.GetCellSize(_elementBefore);
            double afterSize = SplitPanel.GetCellSize(_elementAfter);

            _minElementDelta = DockManager.MinimumAreaSize - _host.CellSizeToSplitterValue(beforeSize);
            _maxElementDelta = _host.CellSizeToSplitterValue(afterSize) - DockManager.MinimumAreaSize;

            _adorner.X = 0;
            _adorner.Y = 0;

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(_host);
            adornerLayer.Add(_adorner);
        }

        private void ThumbDragDelta(DragDeltaEventArgs e) {
            if (_host.Orientation == Orientation.Horizontal) {
                _adorner.X = Math.Max(Math.Min(e.HorizontalChange, _maxElementDelta), _minElementDelta);
            } else {
                _adorner.Y = Math.Max(Math.Min(e.VerticalChange, _maxElementDelta), _minElementDelta);
            }
        }

        private void ThumbDragCompleted(DragCompletedEventArgs e) {
            double change = (_host.Orientation == Orientation.Horizontal) ? _adorner.X : _adorner.Y;
            double beforeSize = SplitPanel.GetCellSize(_elementBefore);
            double afterSize = SplitPanel.GetCellSize(_elementAfter);

            SplitPanel.SetCellSize(_elementBefore, beforeSize + _host.CellSizeFromSplitterValue(change));
            SplitPanel.SetCellSize(_elementAfter, afterSize - _host.CellSizeFromSplitterValue(change));

            AdornerLayer adornerLayer = VisualTreeHelper.GetParent(_adorner) as AdornerLayer;
            adornerLayer.Remove(_adorner);
        }
        #endregion

        #region Overrides
        protected override Size MeasureOverride(Size constraint) {
            return new Size(DockManager.SplitterWidth, DockManager.SplitterWidth);
        }
        #endregion

        #region Event Handlers
        private static void DragStartedHandler(object sender, DragStartedEventArgs e) {
            (sender as SplitPanelSplitter).ThumbDragStarted(e);
        }

        private static void DragDeltaHandler(object sender, DragDeltaEventArgs e) {
            (sender as SplitPanelSplitter).ThumbDragDelta(e);
        }

        private static void DragCompletedHandler(object sender, DragCompletedEventArgs e) {
            (sender as SplitPanelSplitter).ThumbDragCompleted(e);
        }
        #endregion
    }
}
